From b97a0a452f1a2664622205b7aa08c57015070690 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Fri, 31 Aug 2001 01:33:11 +0000 Subject: [PATCH] Instead of always mirroring the selection to a single PRIMARY selection, Wed Aug 29 20:40:58 2001 Owen Taylor * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): Instead of always mirroring the selection to a single PRIMARY selection, allow it to be mirrored to any number of clipboards. * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, just use gtk_text_buffer_paste_clipboard with the appropriate clipboard. * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a GtkClipboard argument, and for paste_clipboard, the @override_location argument from @paste_primary. * gtk/gtktextview.c: Adapt to above change. --- ChangeLog | 15 ++ ChangeLog.pre-2-0 | 15 ++ ChangeLog.pre-2-10 | 15 ++ ChangeLog.pre-2-2 | 15 ++ ChangeLog.pre-2-4 | 15 ++ ChangeLog.pre-2-6 | 15 ++ ChangeLog.pre-2-8 | 15 ++ gtk/gtktextbuffer.c | 463 ++++++++++++++++++++++++++++---------------- gtk/gtktextbuffer.h | 18 +- gtk/gtktextview.c | 35 +++- 10 files changed, 443 insertions(+), 178 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5579b2634b..ecf5313b2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +Wed Aug 29 20:40:58 2001 Owen Taylor + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): + Instead of always mirroring the selection to a single PRIMARY + selection, allow it to be mirrored to any number of clipboards. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, + just use gtk_text_buffer_paste_clipboard with the appropriate clipboard. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a + GtkClipboard argument, and for paste_clipboard, the + @override_location argument from @paste_primary. + + * gtk/gtktextview.c: Adapt to above change. + 2001-08-30 Havoc Pennington * gtk/gtktextview.c (invalidated_handler): put validate idle at diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 5579b2634b..ecf5313b2a 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,18 @@ +Wed Aug 29 20:40:58 2001 Owen Taylor + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): + Instead of always mirroring the selection to a single PRIMARY + selection, allow it to be mirrored to any number of clipboards. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, + just use gtk_text_buffer_paste_clipboard with the appropriate clipboard. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a + GtkClipboard argument, and for paste_clipboard, the + @override_location argument from @paste_primary. + + * gtk/gtktextview.c: Adapt to above change. + 2001-08-30 Havoc Pennington * gtk/gtktextview.c (invalidated_handler): put validate idle at diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 5579b2634b..ecf5313b2a 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,18 @@ +Wed Aug 29 20:40:58 2001 Owen Taylor + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): + Instead of always mirroring the selection to a single PRIMARY + selection, allow it to be mirrored to any number of clipboards. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, + just use gtk_text_buffer_paste_clipboard with the appropriate clipboard. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a + GtkClipboard argument, and for paste_clipboard, the + @override_location argument from @paste_primary. + + * gtk/gtktextview.c: Adapt to above change. + 2001-08-30 Havoc Pennington * gtk/gtktextview.c (invalidated_handler): put validate idle at diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 5579b2634b..ecf5313b2a 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,18 @@ +Wed Aug 29 20:40:58 2001 Owen Taylor + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): + Instead of always mirroring the selection to a single PRIMARY + selection, allow it to be mirrored to any number of clipboards. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, + just use gtk_text_buffer_paste_clipboard with the appropriate clipboard. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a + GtkClipboard argument, and for paste_clipboard, the + @override_location argument from @paste_primary. + + * gtk/gtktextview.c: Adapt to above change. + 2001-08-30 Havoc Pennington * gtk/gtktextview.c (invalidated_handler): put validate idle at diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 5579b2634b..ecf5313b2a 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,18 @@ +Wed Aug 29 20:40:58 2001 Owen Taylor + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): + Instead of always mirroring the selection to a single PRIMARY + selection, allow it to be mirrored to any number of clipboards. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, + just use gtk_text_buffer_paste_clipboard with the appropriate clipboard. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a + GtkClipboard argument, and for paste_clipboard, the + @override_location argument from @paste_primary. + + * gtk/gtktextview.c: Adapt to above change. + 2001-08-30 Havoc Pennington * gtk/gtktextview.c (invalidated_handler): put validate idle at diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 5579b2634b..ecf5313b2a 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,18 @@ +Wed Aug 29 20:40:58 2001 Owen Taylor + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): + Instead of always mirroring the selection to a single PRIMARY + selection, allow it to be mirrored to any number of clipboards. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, + just use gtk_text_buffer_paste_clipboard with the appropriate clipboard. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a + GtkClipboard argument, and for paste_clipboard, the + @override_location argument from @paste_primary. + + * gtk/gtktextview.c: Adapt to above change. + 2001-08-30 Havoc Pennington * gtk/gtktextview.c (invalidated_handler): put validate idle at diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 5579b2634b..ecf5313b2a 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,18 @@ +Wed Aug 29 20:40:58 2001 Owen Taylor + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): + Instead of always mirroring the selection to a single PRIMARY + selection, allow it to be mirrored to any number of clipboards. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, + just use gtk_text_buffer_paste_clipboard with the appropriate clipboard. + + * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a + GtkClipboard argument, and for paste_clipboard, the + @override_location argument from @paste_primary. + + * gtk/gtktextview.c: Adapt to above change. + 2001-08-30 Havoc Pennington * gtk/gtktextview.c (invalidated_handler): put validate idle at diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index 12f36373e8..df584961aa 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -81,7 +81,6 @@ static void gtk_text_buffer_class_init (GtkTextBufferClass *klass); static void gtk_text_buffer_finalize (GObject *object); -static void gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer); static void gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer, GtkTextIter *iter, const gchar *text, @@ -108,6 +107,10 @@ static void gtk_text_buffer_real_changed (GtkTextBuffer *buffe static GtkTextBTree* get_btree (GtkTextBuffer *buffer); static void free_log_attr_cache (GtkTextLogAttrCache *cache); +static void remove_all_clipboard_contents_buffers (GtkTextBuffer *buffer); +static void remove_all_selection_clipboards (GtkTextBuffer *buffer); +static void update_selection_clipboards (GtkTextBuffer *buffer); + static GtkObjectClass *parent_class = NULL; static guint signals[LAST_SIGNAL] = { 0 }; @@ -299,7 +302,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass) void gtk_text_buffer_init (GtkTextBuffer *buffer) { - buffer->clipboard_contents = NULL; + buffer->clipboard_contents_buffers = NULL; } /** @@ -334,12 +337,9 @@ gtk_text_buffer_finalize (GObject *object) buffer = GTK_TEXT_BUFFER (object); - if (buffer->clipboard_contents) - { - g_object_unref (G_OBJECT (buffer->clipboard_contents)); - buffer->clipboard_contents = NULL; - } - + remove_all_clipboard_contents_buffers (buffer); + remove_all_selection_clipboards (buffer); + if (buffer->tag_table) { g_object_unref (G_OBJECT (buffer->tag_table)); @@ -1116,7 +1116,7 @@ gtk_text_buffer_real_delete_range (GtkTextBuffer *buffer, _gtk_text_btree_delete (start, end); /* may have deleted the selection... */ - gtk_text_buffer_update_primary_selection (buffer); + update_selection_clipboards (buffer); g_signal_emit (G_OBJECT (buffer), signals[CHANGED], 0); } @@ -1586,7 +1586,7 @@ gtk_text_buffer_set_mark (GtkTextBuffer *buffer, if (_gtk_text_btree_mark_is_insert (get_btree (buffer), mark) || _gtk_text_btree_mark_is_selection_bound (get_btree (buffer), mark)) { - gtk_text_buffer_update_primary_selection (buffer); + update_selection_clipboards (buffer); } _gtk_text_btree_get_iter_at_mark (get_btree (buffer), @@ -2588,6 +2588,87 @@ clipboard_get_selection_cb (GtkClipboard *clipboard, } } +typedef struct +{ + GtkClipboard *clipboard; + GtkTextBuffer *buffer; +} ContentsBuffer; + +static void +remove_all_clipboard_contents_buffers (GtkTextBuffer *buffer) +{ + GSList *tmp_list = buffer->clipboard_contents_buffers; + while (tmp_list) + { + ContentsBuffer *contents_buffer = tmp_list->data; + + g_object_unref (contents_buffer->buffer); + g_free (contents_buffer); + + tmp_list = tmp_list->next; + } + + g_slist_free (buffer->clipboard_contents_buffers); + buffer->clipboard_contents_buffers = NULL; +} + +static void +remove_clipboard_contents_buffer (GtkTextBuffer *buffer, + GtkClipboard *clipboard) +{ + GSList *tmp_list = buffer->clipboard_contents_buffers; + while (tmp_list) + { + ContentsBuffer *contents_buffer = tmp_list->data; + + if (contents_buffer->clipboard == clipboard) + { + buffer->clipboard_contents_buffers = g_slist_remove (buffer->clipboard_contents_buffers, contents_buffer); + + g_object_unref (contents_buffer->buffer); + g_free (contents_buffer); + + return; + } + + tmp_list = tmp_list->next; + } +} + +static GtkTextBuffer * +get_clipboard_contents_buffer (GtkTextBuffer *buffer, + GtkClipboard *clipboard, + gboolean create) +{ + ContentsBuffer *contents_buffer; + GSList *tmp_list; + + tmp_list = buffer->clipboard_contents_buffers; + while (tmp_list) + { + contents_buffer = tmp_list->data; + if (contents_buffer->clipboard == clipboard) + return contents_buffer->buffer; + } + + if (create) + { + contents_buffer = g_new (ContentsBuffer, 1); + contents_buffer->clipboard = clipboard; + contents_buffer->buffer = gtk_text_buffer_new (gtk_text_buffer_get_tag_table (buffer)); + + g_object_set_data (G_OBJECT (contents_buffer->buffer), "gtk-text-buffer-clipboard", + GUINT_TO_POINTER (1)); + + buffer->clipboard_contents_buffers = g_slist_prepend (buffer->clipboard_contents_buffers, contents_buffer); + + + return contents_buffer->buffer; + } + else + return NULL; +} + /* Provide cut/copied data */ static void clipboard_get_contents_cb (GtkClipboard *clipboard, @@ -2596,7 +2677,9 @@ clipboard_get_contents_cb (GtkClipboard *clipboard, gpointer data) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data); - GtkTextBuffer *contents = buffer->clipboard_contents; + GtkTextBuffer *contents = get_clipboard_contents_buffer (buffer, clipboard, FALSE); + + g_assert (contents); /* This should never be called unless we own the clipboard */ if (selection_data->target == gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE)) @@ -2612,25 +2695,16 @@ clipboard_get_contents_cb (GtkClipboard *clipboard, } else { - /* Just provide text from the clipboard buffer */ - if (buffer->clipboard_contents) - { - gchar *str; - GtkTextIter start, end; - - gtk_text_buffer_get_bounds (contents, &start, &end); - /* strip off the trailing newline, it isn't part of the text that was cut */ - gtk_text_iter_backward_char (&end); - - str = gtk_text_iter_get_visible_text (&start, &end); - gtk_selection_data_set_text (selection_data, str); - g_free (str); - } - else - { - gtk_selection_data_set_text (selection_data, ""); - return; - } + gchar *str; + GtkTextIter start, end; + + gtk_text_buffer_get_bounds (contents, &start, &end); + /* strip off the trailing newline, it isn't part of the text that was cut */ + gtk_text_iter_backward_char (&end); + + str = gtk_text_iter_get_visible_text (&start, &end); + gtk_selection_data_set_text (selection_data, str); + g_free (str); } } @@ -2640,11 +2714,7 @@ clipboard_clear_contents_cb (GtkClipboard *clipboard, { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data); - if (buffer->clipboard_contents) - { - g_object_unref (G_OBJECT (buffer->clipboard_contents)); - buffer->clipboard_contents = NULL; - } + remove_clipboard_contents_buffer (buffer, clipboard); } static void @@ -2849,39 +2919,21 @@ clipboard_clipboard_buffer_received (GtkClipboard *clipboard, { GtkTextIter start, end; - gtk_text_buffer_get_bounds (src_buffer, &start, &end); - /* There's an extra newline on clipboard_contents */ - gtk_text_iter_backward_char (&end); + if (g_object_get_data (G_OBJECT (src_buffer), "gtk-text-buffer-clipboard")) + { + gtk_text_buffer_get_bounds (src_buffer, &start, &end); + /* There's an extra newline on clipboard_contents */ + gtk_text_iter_backward_char (&end); - paste_from_buffer (request_data, src_buffer, - &start, &end); - } - else - { - /* Request the text selection instead */ - gtk_clipboard_request_text (clipboard, - clipboard_text_received, - data); - } -} - -static void -clipboard_selection_buffer_received (GtkClipboard *clipboard, - GtkSelectionData *selection_data, - gpointer data) -{ - ClipboardRequest *request_data = data; - GtkTextBuffer *src_buffer; - - src_buffer = selection_data_get_buffer (selection_data, request_data); - - if (src_buffer) - { - GtkTextIter start, end; - - if (gtk_text_buffer_get_selection_bounds (src_buffer, &start, &end)) - paste_from_buffer (request_data, src_buffer, - &start, &end); + paste_from_buffer (request_data, src_buffer, + &start, &end); + } + else + { + if (gtk_text_buffer_get_selection_bounds (src_buffer, &start, &end)) + paste_from_buffer (request_data, src_buffer, + &start, &end); + } } else { @@ -2900,49 +2952,179 @@ static const GtkTargetEntry targets[] = { { "GTK_TEXT_BUFFER_CONTENTS", 0, TARGET_TEXT_BUFFER_CONTENTS } }; +typedef struct +{ + GtkClipboard *clipboard; + guint ref_count; +} SelectionClipboard; + static void -gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer) +update_selection_clipboards (GtkTextBuffer *buffer) { - GtkTextIter start; - GtkTextIter end; + GSList *tmp_list = buffer->selection_clipboards; + while (tmp_list) + { + GtkTextIter start; + GtkTextIter end; + + SelectionClipboard *selection_clipboard = tmp_list->data; + GtkClipboard *clipboard = selection_clipboard->clipboard; - GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); + /* Determine whether we have a selection and adjust X selection + * accordingly. + */ + if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end)) + { + if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (buffer)) + gtk_clipboard_clear (clipboard); + } + else + { + /* Even if we already have the selection, we need to update our + * timestamp. + */ + if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets), + clipboard_get_selection_cb, + clipboard_clear_selection_cb, + G_OBJECT (buffer))) + clipboard_clear_selection_cb (clipboard, buffer); + } - /* Determine whether we have a selection and adjust X selection - * accordingly. - */ + tmp_list = tmp_list->next; + } +} - if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end)) +static SelectionClipboard * +find_selection_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard) +{ + GSList *tmp_list = buffer->selection_clipboards; + while (tmp_list) + { + SelectionClipboard *selection_clipboard = tmp_list->data; + if (selection_clipboard->clipboard == clipboard) + return selection_clipboard; + + tmp_list = tmp_list->next; + } + + return NULL; +} + +/** + * gtk_text_buffer_add_selection_clipboard: + * @buffer: a #GtkTextBuffer + * @clipboard: a #GtkClipboard + * + * Adds @clipboard to the list of clipboards in which the selection contents + * of @buffer are available. In most cases, @clipboard will be the #GtkClipboard + * of type %GDK_SELECTION_PRIMARY for a view of @buffer. + **/ +void +gtk_text_buffer_add_selection_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard) +{ + SelectionClipboard *selection_clipboard; + + g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); + g_return_if_fail (clipboard != NULL); + + selection_clipboard = find_selection_clipboard (buffer, clipboard); + if (selection_clipboard) { - if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (buffer)) - gtk_clipboard_clear (clipboard); + selection_clipboard->ref_count++; } else { - /* Even if we already have the selection, we need to update our - * timestamp. - */ - if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets), - clipboard_get_selection_cb, - clipboard_clear_selection_cb, - G_OBJECT (buffer))) - clipboard_clear_selection_cb (clipboard, buffer); + selection_clipboard = g_new (SelectionClipboard, 1); + + selection_clipboard->clipboard = clipboard; + selection_clipboard->ref_count = 1; + + buffer->selection_clipboards = g_slist_prepend (buffer->selection_clipboards, selection_clipboard); + } +} + +/** + * gtk_text_buffer_remove_selection_clipboard: + * @buffer: a #GtkTextBuffer + * @clipboard: a #GtkClipboard added to @buffer by gtk_text_buffer_add_selection_clipboard(). + * + * Removes a #GtkClipboard added with gtk_text_buffer_add_selection_clipboard() + **/ +void +gtk_text_buffer_remove_selection_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard) +{ + SelectionClipboard *selection_clipboard; + + g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); + g_return_if_fail (clipboard != NULL); + + selection_clipboard = find_selection_clipboard (buffer, clipboard); + g_return_if_fail (selection_clipboard != NULL); + + selection_clipboard->ref_count--; + if (selection_clipboard->ref_count == 0) + { + if (gtk_clipboard_get_owner (selection_clipboard->clipboard) == G_OBJECT (buffer)) + gtk_clipboard_clear (selection_clipboard->clipboard); + + g_free (selection_clipboard); } } static void -paste (GtkTextBuffer *buffer, - gboolean is_clipboard, - gboolean interactive, - gboolean default_editable) +remove_all_selection_clipboards (GtkTextBuffer *buffer) +{ + GSList *tmp_list = buffer->selection_clipboards; + while (tmp_list) + { + SelectionClipboard *selection_clipboard = tmp_list->data; + + if (gtk_clipboard_get_owner (selection_clipboard->clipboard) == G_OBJECT (buffer)) + gtk_clipboard_clear (selection_clipboard->clipboard); + + g_free (selection_clipboard); + + tmp_list = tmp_list->next; + } + + g_slist_free (buffer->selection_clipboards); + buffer->selection_clipboards = NULL; +} + +/** + * gtk_text_buffer_paste_clipboard: + * @buffer: a #GtkTextBuffer + * @clipboard: the #GtkClipboard to paste from + * @override_location: location to insert pasted text, or %NULL for at the cursor + * @default_editable: whether the buffer is editable by default + * + * Pastes the contents of a clipboard at the insertion point, or at @override_location. + * (Note: pasting is asynchronous, that is, we'll ask for the paste data and + * return, and at some point later after the main loop runs, the paste + * data will be inserted.) + * + **/ +void +gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard, + GtkTextIter *override_location, + gboolean default_editable) { ClipboardRequest *data = g_new (ClipboardRequest, 1); GtkTextIter paste_point; GtkTextIter start, end; - + + if (override_location != NULL) + gtk_text_buffer_create_mark (buffer, + "gtk_paste_point_override", + override_location, FALSE); + data->buffer = buffer; g_object_ref (G_OBJECT (buffer)); - data->interactive = interactive; + data->interactive = TRUE; data->default_editable = default_editable; /* When pasting with the cursor inside the selection area, you @@ -2959,58 +3141,9 @@ paste (GtkTextBuffer *buffer, gtk_text_iter_equal (&paste_point, &end))) data->replace_selection = TRUE; - if (is_clipboard) - gtk_clipboard_request_contents (gtk_clipboard_get (GDK_NONE), - - gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE), - clipboard_clipboard_buffer_received, data); - else - gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_PRIMARY), - - gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE), - clipboard_selection_buffer_received, data); -} - -/** - * gtk_text_buffer_paste_primary: - * @buffer: a #GtkTextBuffer - * @override_location: location to insert pasted text, or %NULL for at the cursor - * @default_editable: whether the buffer is editable by default - * - * Pastes the primary selection at the insertion point, or at @override_location. - * (Note: pasting is asynchronous, that is, we'll ask for the paste data - * and return, and at some point later after the main loop runs, the paste - * data will be inserted.) - **/ -void -gtk_text_buffer_paste_primary (GtkTextBuffer *buffer, - const GtkTextIter *override_location, - gboolean default_editable) -{ - if (override_location != NULL) - gtk_text_buffer_create_mark (buffer, - "gtk_paste_point_override", - override_location, FALSE); - - paste (buffer, FALSE, TRUE, default_editable); -} - -/** - * gtk_text_buffer_paste_clipboard: - * @buffer: a #GtkTextBuffer - * @default_editable: whether the buffer is editable by default - * - * Pastes the clipboard contents at the insertion point. (Note: - * pasting is asynchronous, that is, we'll ask for the paste data and - * return, and at some point later after the main loop runs, the paste - * data will be inserted.) - * - **/ -void -gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer, - gboolean default_editable) -{ - paste (buffer, TRUE, TRUE, default_editable); + gtk_clipboard_request_contents (clipboard, + gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE), + clipboard_clipboard_buffer_received, data); } /** @@ -3055,9 +3188,10 @@ gtk_text_buffer_delete_selection (GtkTextBuffer *buffer, static void cut_or_copy (GtkTextBuffer *buffer, - gboolean delete_region_after, - gboolean interactive, - gboolean default_editable) + GtkClipboard *clipboard, + gboolean delete_region_after, + gboolean interactive, + gboolean default_editable) { /* We prefer to cut the selected region between selection_bound and * insertion point. If that region is empty, then we cut the region @@ -3068,12 +3202,8 @@ cut_or_copy (GtkTextBuffer *buffer, */ GtkTextIter start; GtkTextIter end; - - if (buffer->clipboard_contents) - { - g_object_unref (G_OBJECT (buffer->clipboard_contents)); - buffer->clipboard_contents = NULL; - } + + remove_clipboard_contents_buffer (buffer, clipboard); if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end)) { @@ -3091,19 +3221,14 @@ cut_or_copy (GtkTextBuffer *buffer, if (!gtk_text_iter_equal (&start, &end)) { - GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE); GtkTextIter ins; + GtkTextBuffer *contents; - buffer->clipboard_contents = - gtk_text_buffer_new (gtk_text_buffer_get_tag_table (buffer)); + contents = get_clipboard_contents_buffer (buffer, clipboard, TRUE); - gtk_text_buffer_get_iter_at_offset (buffer->clipboard_contents, - &ins, 0); + gtk_text_buffer_get_iter_at_offset (contents, &ins, 0); - gtk_text_buffer_insert_range (buffer->clipboard_contents, - &ins, - &start, - &end); + gtk_text_buffer_insert_range (contents, &ins, &start, &end); if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets), clipboard_get_contents_cb, @@ -3124,34 +3249,38 @@ cut_or_copy (GtkTextBuffer *buffer, /** * gtk_text_buffer_cut_clipboard: - * @buffer: a #GtkTextBuffer + * @buffer: a #GtkTextBuffer + * @clipboard: the #GtkClipboard object to cut to. * @default_editable: default editability of the buffer * - * Copies the currently-selected text to the clipboard, then deletes + * Copies the currently-selected text to a clipboard, then deletes * said text if it's editable. * **/ void gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard, gboolean default_editable) { gtk_text_buffer_begin_user_action (buffer); - cut_or_copy (buffer, TRUE, TRUE, default_editable); + cut_or_copy (buffer, clipboard, TRUE, TRUE, default_editable); gtk_text_buffer_end_user_action (buffer); } /** * gtk_text_buffer_copy_clipboard: * @buffer: a #GtkTextBuffer + * @clipboard: the #GtkClipboard object to copy to. * - * Copies the currently-selected text to the clipboard. + * Copies the currently-selected text to a clipboard. * **/ void -gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer) +gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard) { gtk_text_buffer_begin_user_action (buffer); - cut_or_copy (buffer, FALSE, TRUE, TRUE); + cut_or_copy (buffer, clipboard, FALSE, TRUE, TRUE); gtk_text_buffer_end_user_action (buffer); } diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h index bfaafd2206..24311f8885 100644 --- a/gtk/gtktextbuffer.h +++ b/gtk/gtktextbuffer.h @@ -28,6 +28,7 @@ #define GTK_TEXT_BUFFER_H #include +#include #include #include #include @@ -62,7 +63,8 @@ struct _GtkTextBuffer GtkTextTagTable *tag_table; GtkTextBTree *btree; - GtkTextBuffer *clipboard_contents; + GSList *clipboard_contents_buffers; + GSList *selection_clipboards; GtkTextLogAttrCache *log_attr_cache; @@ -324,13 +326,19 @@ gboolean gtk_text_buffer_get_modified (GtkTextBuffer *buffer); void gtk_text_buffer_set_modified (GtkTextBuffer *buffer, gboolean setting); -void gtk_text_buffer_paste_primary (GtkTextBuffer *buffer, - const GtkTextIter *override_location, - gboolean default_editable); +void gtk_text_buffer_add_selection_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard); +void gtk_text_buffer_remove_selection_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard); + void gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard, gboolean default_editable); -void gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer); +void gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard); void gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer, + GtkClipboard *clipboard, + GtkTextIter *override_location, gboolean default_editable); gboolean gtk_text_buffer_get_selection_bounds (GtkTextBuffer *buffer, diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index 71a3e1c469..3c10bbbc54 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -1050,6 +1050,10 @@ gtk_text_view_set_buffer (GtkTextView *text_view, gtk_text_view_mark_set_handler, text_view); g_object_unref (G_OBJECT (text_view->buffer)); text_view->dnd_mark = NULL; + + if (GTK_WIDGET_REALIZED (text_view)) + gtk_text_buffer_remove_selection_clipboard (text_view->buffer, + gtk_clipboard_get (GDK_SELECTION_PRIMARY)); } text_view->buffer = buffer; @@ -1077,6 +1081,10 @@ gtk_text_view_set_buffer (GtkTextView *text_view, g_signal_connect (G_OBJECT (text_view->buffer), "mark_set", G_CALLBACK (gtk_text_view_mark_set_handler), text_view); + + if (GTK_WIDGET_REALIZED (text_view)) + gtk_text_buffer_remove_selection_clipboard (text_view->buffer, + gtk_clipboard_get (GDK_SELECTION_PRIMARY)); } if (GTK_WIDGET_VISIBLE (text_view)) @@ -2939,6 +2947,10 @@ gtk_text_view_realize (GtkWidget *widget) widget->window); gtk_text_view_ensure_layout (text_view); + + if (text_view->buffer) + gtk_text_buffer_add_selection_clipboard (text_view->buffer, + gtk_clipboard_get (GDK_SELECTION_PRIMARY)); } static void @@ -2948,6 +2960,10 @@ gtk_text_view_unrealize (GtkWidget *widget) text_view = GTK_TEXT_VIEW (widget); + if (text_view->buffer) + gtk_text_buffer_remove_selection_clipboard (text_view->buffer, + gtk_clipboard_get (GDK_SELECTION_PRIMARY)); + if (text_view->first_validate_idle) { g_source_remove (text_view->first_validate_idle); @@ -3290,9 +3306,10 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event) event->x + text_view->xoffset, event->y + text_view->yoffset); - gtk_text_buffer_paste_primary (get_buffer (text_view), - &iter, - text_view->editable); + gtk_text_buffer_paste_clipboard (get_buffer (text_view), + gtk_clipboard_get (GDK_SELECTION_PRIMARY), + &iter, + text_view->editable); return TRUE; } else if (event->button == 3) @@ -4170,7 +4187,9 @@ gtk_text_view_delete_from_cursor (GtkTextView *text_view, static void gtk_text_view_cut_clipboard (GtkTextView *text_view) { - gtk_text_buffer_cut_clipboard (get_buffer (text_view), text_view->editable); + gtk_text_buffer_cut_clipboard (get_buffer (text_view), + gtk_clipboard_get (GDK_NONE), + text_view->editable); DV(g_print (G_STRLOC": scrolling onscreen\n")); gtk_text_view_scroll_mark_onscreen (text_view, gtk_text_buffer_get_mark (get_buffer (text_view), @@ -4180,7 +4199,8 @@ gtk_text_view_cut_clipboard (GtkTextView *text_view) static void gtk_text_view_copy_clipboard (GtkTextView *text_view) { - gtk_text_buffer_copy_clipboard (get_buffer (text_view)); + gtk_text_buffer_copy_clipboard (get_buffer (text_view), + gtk_clipboard_get (GDK_NONE)); DV(g_print (G_STRLOC": scrolling onscreen\n")); gtk_text_view_scroll_mark_onscreen (text_view, gtk_text_buffer_get_mark (get_buffer (text_view), @@ -4190,7 +4210,10 @@ gtk_text_view_copy_clipboard (GtkTextView *text_view) static void gtk_text_view_paste_clipboard (GtkTextView *text_view) { - gtk_text_buffer_paste_clipboard (get_buffer (text_view), text_view->editable); + gtk_text_buffer_paste_clipboard (get_buffer (text_view), + gtk_clipboard_get (GDK_NONE), + NULL, + text_view->editable); DV(g_print (G_STRLOC": scrolling onscreen\n")); gtk_text_view_scroll_mark_onscreen (text_view, gtk_text_buffer_get_mark (get_buffer (text_view), -- 2.30.2